package security;

import java.util.LinkedHashMap;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.userdetails.User;
import org.springframework.security.userdetails.UserDetails;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.security.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;

public class SieciloAuthenticationProvider implements UserDetailsService, ApplicationContextAware {

    private ApplicationContext appContext;
    private JdbcTemplate jdbcTemplate;
    String efx_ds_server_url = null;

    @Override
    public UserDetails loadUserByUsername(String principal)
            throws UsernameNotFoundException, DataAccessException {
        User user = null;
        
        try {
            final String[] tokens = StringUtils.split(principal, "$");

            if (tokens != null && tokens.length == 2) {

                final String codigoUsuario = tokens[0];
                final String passwordUsuario = tokens[1];

                String sql ="SELECT " +
                                " U.NOMBREUSUARIO AS USERNAME, U.PASSWORD AS PASSWORD, U.ESTADOUSUARIO AS ENABLED " +
                            " FROM " +
                                " USUARIO U " +
                            " WHERE " +
                                " U.NOMBREUSUARIO = ?";
                String params[] = {codigoUsuario};
                List<LinkedHashMap> resultado = null;
                resultado = jdbcTemplate.queryForList(sql, params);

               

                if(resultado==null){
                    throw new CustomAuthenticationException("AUTENTIFICACION FALLIDA.");
                //PROBLEMAS PARA AUTENTICARSE, INTENTE DE NUEVO. SI LOS PROBLEMAS PERSISTEN COMUNICARSE CON EL ADMINISTRADOR DEL SISTEMA
                }

                if (resultado.size() > 0) {
                    String clave = (String) resultado.get(0).get("password");
                    boolean userOK = passwordUsuario.equals(clave);
                    if (!userOK) {
                        throw new CustomAuthenticationException("AUTENTIFICACION FALLIDA.");
                    //CONTRASEÑA NO CORRESPONDE AL USUARIO
                    }
                } else {
                    //USUARIO NO EXISTE EN LA BASE DE DATOS. RECUERDE CAMPO USUARIO DISTINGUE ENTRE MAYUSCULAS Y MINUSCULAS
                    throw new CustomAuthenticationException("AUTENTIFICACION FALLIDA.");
                }
                sql =       " SELECT " +
                                " P.IDPERFIL, P.NOMBREPERFIL, PA.AUTORIDAD AS ROL" +
                            " FROM " +
                                " PERFIL P, PERFIL_MIEMBRO PM, PERFIL_AUTORIDAD PA " +
                            " WHERE " +
                                " PM.IDUSUARIO = (SELECT USUARIO.IDUSUARIO FROM USUARIO WHERE (USUARIO.NOMBREUSUARIO) = (?)) " +
                                " AND P.IDPERFIL = PA.IDPERFIL " +
                                " AND P.IDPERFIL = PM.IDPERFIL ";
                resultado = jdbcTemplate.queryForList(sql, params);

                if(resultado==null){
                    throw new CustomAuthenticationException("AUTENTIFICACION FALLIDA.");
                }

                SieciloAuthority[] authorities = null;
                    int h=0;
                    authorities = new SieciloAuthority[resultado.size()];
                    for(LinkedHashMap<String,String> res: resultado){
                        authorities[h] = new SieciloAuthority();
                        authorities[h].setAuthority(res.get("rol"));
                        h++;
                    }
                user = new User(codigoUsuario,
                                passwordUsuario,
                                true,
                                true,
                                true,
                                true,
                                authorities);
            }
        } catch (CannotGetJdbcConnectionException e) {
            throw new CustomAuthenticationException("NO SE PUDO REALIZAR LA CONEXION A LA BASE DE DATOS, COMUNIQUESE CON EL ADMINISTRADOR DE SISTEMA. VERIFIQUE LAS PROPIEDADES DE CONEXION , COMPRUEBE QUE HAY UNA INSTANCIA DE BASE DE DATOS EJECUTANDOSE Y ACEPTANDO CONEXIONES");
        } catch (CustomAuthenticationException e) {
            throw e;
        }
        return user;
    }

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        this.appContext = appContext;
    }
}
